package jmine.tec.utils.reflection.fast.asm;

import java.lang.reflect.Method;

import jmine.tec.utils.reflection.fast.FastMethod;

/**
 * Representa um handler para um metodo compilado
 * 
 * @author takeshi
 */
public abstract class CompiledFastMethod implements FastMethod {

    /**
     * Faz a invocacao do metodo
     * 
     * @param target Object
     * @param args Object[]
     * @return Object
     * @throws Exception a excecao lancada pelo metodo original
     */
    public abstract Object invoke(Object target, Object... args) throws Exception;

    private volatile Method targetMethod;

    /**
     * Faz a invocacao de um metodo com 1 argumento
     * 
     * @param target alvo
     * @param arg argumento
     * @return Object
     * @throws Exception a excecao lancada
     */
    public Object invokeSingleArgument(Object target, Object arg) throws Exception {
        throw new IllegalArgumentException("wrong number of arguments for target method");
    }

    /**
     * Faz a invocacao de um metodo com nenhum argumento
     * 
     * @param target alvo
     * @return Object
     * @throws Exception e
     */
    public Object invokeNoArgs(Object target) throws Exception {
        throw new IllegalArgumentException("wrong number of arguments for target method");
    }

    /**
     * @return the targetMethod
     */
    public final Method getTargetMethod() {
        return this.targetMethod;
    }

    /**
     * @param targetMethod the targetMethod to set
     */
    final void setTargetMethod(Method targetMethod) {
        this.targetMethod = targetMethod;
    }

    /**
     * {@inheritDoc}
     */
    public final Method getMethod() {
        return this.targetMethod;
    }

    /**
     * {@inheritDoc}
     */
    public String getName() {
        return this.targetMethod.getName();
    }

    /**
     * {@inheritDoc}
     */
    public int getArity() {
        return this.getArgumentTypes().length;
    }

    /**
     * {@inheritDoc}
     */
    public Class<?>[] getArgumentTypes() {
        return this.targetMethod.getParameterTypes();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String toString() {
        return "method accessor for: " + this.targetMethod;
    }

}
